using System.Linq;
using FireStarter.Base;
using Habanero.Util;

namespace FireStarterModeller.BO
{
    public class RelationshipNameGenerator : IRelationshipNameGenerator
    {
        public string CreateRelationshipName(IDMRelationship relationship)
        {
            return !string.IsNullOrEmpty(relationship.RelationshipName) 
                    ? relationship.RelationshipName 
                    : RenameRelationship(relationship);
        }
        public string RenameRelationship(IDMRelationship relationship)
        {
            return relationship.IsMultiple 
                    ? GetMultipleRelationshipName(relationship) 
                    : GetSingleRelationshipName(relationship);
        }

        private static string GetSingleRelationshipName(IDMRelationship relationship)
        {
            if (relationship.RelationshipProperties == null) return relationship.RelatedClassName;
            //If this is a one to one and the relationship has the Primary
            // Key then use the Related Class Name
            // Otherwise use the PropertyName.
            //If has duplicate then append a ownerClass

            string relName = DetermineInitialName(relationship);

            if (RelationshipWithNameAlreadyExistsOnClass(relationship, relName))
            {
                return relName + relationship.OwnerClassName;
            }
            return relName;
        }

        private static string DetermineInitialName(IDMRelationship relationship)
        {
            if (relationship.HasAllPkProps() || relationship.RelationshipProperties.Count == 0)
            {
                return relationship.RelatedClassName;
            }
            string ownerPropertyName = relationship.RelationshipProperties.First().OwnerPropertyName;
            if (string.IsNullOrEmpty(ownerPropertyName))
            {
                return relationship.RelatedClassName;
            }
            if(ownerPropertyName.EndsWith("ID")) 
            {
                return RemoveIDSuffix(ownerPropertyName);
            }
            return relationship.OwnerClassName + ownerPropertyName;
        }

        private static string GetMultipleRelationshipName(IDMRelationship relationship)
        {
            var relName = StringUtilities.Pluralize(relationship.RelatedClassName);

            if (RelationshipWithNameAlreadyExistsOnClass(relationship, relName))
            {
                var relatedPropName = relationship.RelationshipProperties.First().RelatedPropertyName;
                relName = relName + relatedPropName + relationship.OwnerClassName;
            }
            return relName;
        }

        private static bool RelationshipWithNameAlreadyExistsOnClass(IDMRelationship relationship, string relName)
        {
            var foundRealationship = GetRelationship(relationship.OwnerClass, relName);
            return foundRealationship != null && foundRealationship != relationship;
        }

        private static DMRelationship GetRelationship(IDMClass ownerClass, string relName)
        {
            if (ownerClass == null) return null;
            if (ownerClass.RelationshipsDM == null) return null;
            return ownerClass.RelationshipsDM.Find(
                dmRelationship => dmRelationship.RelationshipName == relName);
        }

        private static string RemoveIDSuffix(string parentPropertyName)
        {
            return parentPropertyName.Substring(0, parentPropertyName.LastIndexOf("ID"));
        }
    }
}